iT邦幫忙

2021 iThome 鐵人賽

DAY 24
1

這次,需求單位又提出了一個新的想法:
我們可不可以設計一個 API,允許用戶在 2021/12/31 23:59:59 之前才能參加該活動。之後的用戶都不允許參加活動呢?

參與活動的邏輯很簡單,只是新增資料而已。這段我們不擔心。不過針對時間的限制,該怎麼在自動測試裡面進行控制呢?

今天我們就來聊聊這個部分!

驗證時間

首先,我們先來撰寫驗證時間的邏輯 isValidDate(),如果現在時間還沒到 2021/12/31 23:59:59 回傳 true,其餘時間回傳 false

這邊我們利用 java.time.* 套件

import java.time.*
 
fun isValidDate(): Boolean {
    val clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"))
    val now = LocalDateTime.now(clock)
    val dueDate = LocalDateTime.parse("2021-12-31T23:59:59")
    return dueDate.isAfter(now)
}

邏輯撰寫好了之後,我們先簡單的測試一下

建立一個 IsValidDateKtTest.kt 並撰寫以下邏輯

import org.junit.Test

internal class IsValidDateKtTest {

    @Test
    fun `確認isValidDate`() {
        println(isValidDate())
    }
}

運行過後,我們可以看到確實印出 true

可是我們並不知道在其他的時間裡,特別是超過

這邊,我們要介紹一個協助我們建立 test double 的框架:mockk!

mockk

簡單說,mockk 是一個測試時協助我們在測試時,建立 test double 的框架。

引用的方式一樣透過 gradle,相信各位都很熟悉了

testImplementation("io.mockk:mockk:1.12.0")

引入之後,我們就可以利用 mockk 框架來協助我們假造 LocalDateTime.now()

我們想測試的案例是 在2022/01/01時應該回傳false

在程式裡面,我們取得現在時間的邏輯是

val clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"))  
val now = LocalDateTime.now(clock)

我們透過把 clock 寫死

來控制測試執行的時間是 2022-01-01T23:59:59

fun `確認isValidDate`() {  
    val fixedClock = Clock.fixed(
	    Instant.parse("2022-01-01T23:59:59Z"),
		ZoneId.of("UTC")
	)  
    mockkStatic(Clock::class)  
    every { Clock.systemUTC() } returns fixedClock  
}

我們如果先將 isValidDate() 改寫,看看實際取得的 now() 內容

val clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"))  
val now = LocalDateTime.now(clock)  
val dueDate = LocalDateTime.parse("2021-12-31T23:59:59")  
println(now)

會印出

2022-01-01T23:59:59

這代表,透過假造我們的 Clock 物件,我們可以在測試程式裡面控制我們的時間了!

現在我們可以將 在2022-01-01時應該回傳false() 寫完

@Test
fun `在2022-01-01時應該回傳false`() {
	val fixedClock = Clock.fixed(
		Instant.parse("2022-01-01T23:59:59Z"),
		ZoneId.of("UTC")
	)
	mockkStatic(Clock::class)
	every { Clock.systemUTC() } returns fixedClock
	Assert.assertThat(isValidDate(), `is`(false))
}

執行並確認通過之後,我們可以趁機再加上 在2021-12-30時應該回傳true

@Test  
fun `在2021-12-30時應該回傳true`() {  
    val fixedClock = Clock.fixed(  
        Instant.parse("2021-12-30T23:59:59Z"),  
 ZoneId.of("UTC")  
    )  
    mockkStatic(Clock::class)  
    every { Clock.systemUTC() } returns fixedClock  
    Assert.assertThat(isValidDate(), `is`(true))  
}

這樣,我們的 isValidDate() 功能和測試就寫完了!


上一篇
[Day 23] 撰寫我們的第一個 test double
下一篇
[Day 25] 如果我們不想 mock Clock 怎麼辦呢?談依賴反轉
系列文
Kotlin 怎麼操作資料庫?談談 Kotlin Exposed 框架30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言